#include <arch.h>
#include <conio.h>
#include <cpu.h>
#include <assert.h>
#include <exc.h>

/* change all to arch_panic() */
EXCEPTION_HANDLER(exc00Handler)
{
    arch_panic("Exception 0x00: division by zero!\n");
}

EXCEPTION_HANDLER(exc01Handler)
{
    asm("pushl %eax");
    asm("movl $0,%eax");
    asm("movl %eax,%dr6");
    asm("movl %eax,%dr7");
    asm("popl %eax");
}

EXCEPTION_HANDLER(exc02Handler)
{
    arch_panic("Exception 0x02: interrupt NMI!\n");
}

EXCEPTION_HANDLER(exc03Handler)
{
    asm("nop");
}

EXCEPTION_HANDLER(exc04Handler)
{;
    arch_panic("Exception 0x04: overflow error!\n");
}

EXCEPTION_HANDLER(exc05Handler)
{
    arch_panic("Exception 0x05: overflow by checking BOUND!\n");
}

EXCEPTION_HANDLER(exc06Handler)
{
    arch_panic("Exception 0x06: inknown instruction!\n");
}

EXCEPTION_HANDLER(exc07Handler)
{
    arch_panic("Exception 0x07: not found FPU!\n");
}

EXCEPTION_HANDLER(exc08Handler)
{
    arch_panic("Exception 0x08: double error!\n");
}

EXCEPTION_HANDLER(exc09Handler)
{
    arch_panic("Exception 0x09: reserved!\n");
}

EXCEPTION_HANDLER(exc0AHandler)
{
    setcolor(0x0c);
    kprintf("Exception 0x0A: Failed TSS error 0x%lx, at 0x%p\n",
	    errcode, address);
    asm("cli");
    asm("hlt");
}

EXCEPTION_HANDLER(exc0BHandler)
{
    setcolor(0x0c);
    kprintf("Exception 0x0B: Segment not found - error 0x%lx!\n", errcode);
    asm("cli");
    asm("hlt");
}

EXCEPTION_HANDLER(exc0CHandler)
{
    setcolor(0x0c);
    kprintf("Exception 0x0C: Error in stack, error 0x%lx!\n", errcode);
    asm("cli");
    asm("hlt");
}

EXCEPTION_HANDLER(exc0DHandler)
{
    setcolor(0x0c);
    kprintf("Exception 0x0D: General protection fault, error 0x%lx at 0x%p\n",
	 errcode, address);
    asm("cli");
    asm("hlt");
}


EXCEPTION_HANDLER(exc0EHandler)
{
    uint32_t cr2;

    asm("movl %%cr2,%0":"=d"(cr2));
    asm("xor %eax,%eax");
    asm("movl %eax,%cr2");

    setcolor(0x0c);
    kprintf("Exception 0x0E: page fault, CR2=0x%lx, error=0x%lx, EIP=0x%lx\n",
	 cr2, errcode, address);

    kprintf("System halted.\n");
    asm("cli");
    asm("hlt");
}

EXCEPTION_HANDLER(exc0FHandler)
{
    arch_panic("Exception 0x0F: reserved!\n");
}

EXCEPTION_HANDLER(exc10Handler)
{
    setcolor(0x0c);
    kprintf("Exception 0x10: FPU error!\n");
    asm("cli");
    asm("hlt");
}

EXCEPTION_HANDLER(exc11Handler)
{
    arch_panic("Exception 0x11: aligment error!\n");
}

EXCEPTION_HANDLER(exc12Handler)
{
    kprintf("Exception 0x12: machine dependent error!\n");
}

void init_exc()
{
    kprintf("install exception handlers...");

    add_idtexc((uint32_t *) idt, 0, SEL_KCODE, exc00Handler);
    add_idtexc((uint32_t *) idt, 1, SEL_KCODE, exc01Handler);
    add_idtexc((uint32_t *) idt, 2, SEL_KCODE, exc03Handler);
    add_idtexc((uint32_t *) idt, 4, SEL_KCODE, exc04Handler);
    add_idtexc((uint32_t *) idt, 5, SEL_KCODE, exc05Handler);
    add_idtexc((uint32_t *) idt, 6, SEL_KCODE, exc06Handler);
    add_idtexc((uint32_t *) idt, 7, SEL_KCODE, exc07Handler);
    add_idtexc((uint32_t *) idt, 8, SEL_KCODE, exc08Handler);
    add_idtexc((uint32_t *) idt, 9, SEL_KCODE, exc09Handler);
    add_idtexc((uint32_t *) idt, 10, SEL_KCODE, exc0AHandler);
    add_idtexc((uint32_t *) idt, 11, SEL_KCODE, exc0BHandler);
    add_idtexc((uint32_t *) idt, 12, SEL_KCODE, exc0CHandler);
    add_idtexc((uint32_t *) idt, 13, SEL_KCODE, exc0DHandler);
    add_idtexc((uint32_t *) idt, 14, SEL_KCODE, exc0EHandler);
    add_idtexc((uint32_t *) idt, 15, SEL_KCODE, exc0FHandler);
    add_idtexc((uint32_t *) idt, 16, SEL_KCODE, exc10Handler);
    add_idtexc((uint32_t *) idt, 17, SEL_KCODE, exc11Handler);
    add_idtexc((uint32_t *) idt, 18, SEL_KCODE, exc12Handler);

    kprintf("Ok.\n");
}
